package org.linlinjava.litemall.admin.controller.giftcards;

import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.linlinjava.litemall.admin.beans.annotation.LogAnno;
import org.linlinjava.litemall.admin.beans.annotation.LoginAdminId;
import org.linlinjava.litemall.admin.beans.vo.*;
import org.linlinjava.litemall.admin.controller.giftcards.vo.*;
import org.linlinjava.litemall.admin.util.PageUtil;
import org.linlinjava.litemall.admin.vo.LitemallGiftCardOrderVO;
import org.linlinjava.litemall.core.util.BigDecimalUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.BeanUtil;
import org.linlinjava.litemall.db.util.CollectionUtils;
import org.linlinjava.litemall.db.util.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Api(tags = "管理礼物卡控制器")
@RestController
@RequestMapping("/admin/giftcard")
public class AdminGiftCardController {

    @Autowired
    private LitemallGiftCardService litemallGiftCardService;

    @Autowired
    private LitemallUserService litemallUserService;

    @Autowired
    private LitemallAdminService litemallAdminService;

    @Autowired
    private LitemallGiftCardUserService litemallGiftCardUserService;

    @Autowired
    private LitemallShopService litemallShopService;

    @Autowired
    private LitemallGiftCardUserLogService litemallGiftCardUserLogService;

    @Autowired
    private LitemallGiftCardOrderService litemallGiftCardOrderService;

    @Autowired
    private LitemallGiftCardClassificationService litemallGiftCardClassificationService;


    @ApiOperation("列表")
    @GetMapping("/list")
    @LogAnno
    public Object page(AdminGiftCardPageReqVO pageReqVO) {
        LambdaQueryWrapper<LitemallGiftCard> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        Optional.ofNullable(pageReqVO.getUserId())
                .ifPresent(userId -> lambdaQueryWrapper.like(LitemallGiftCard::getAddUserId, userId));
        Optional.ofNullable(pageReqVO.getName())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(name -> lambdaQueryWrapper.like(LitemallGiftCard::getName, name));
        Optional.ofNullable(pageReqVO.getCardNo())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(cardNo -> lambdaQueryWrapper.like(LitemallGiftCard::getCardNo, cardNo));
        Optional.ofNullable(pageReqVO.getType())
                .ifPresent(type -> lambdaQueryWrapper.eq(LitemallGiftCard::getType, type));
        Optional.ofNullable(pageReqVO.getStatus())
                .ifPresent(status -> lambdaQueryWrapper.eq(LitemallGiftCard::getStatus, status));
        Optional.ofNullable(pageReqVO.getClassificationId())
                .ifPresent(classificationId -> lambdaQueryWrapper.eq(LitemallGiftCard::getClassificationId, classificationId));
        lambdaQueryWrapper.eq(LitemallGiftCard::getDeleted,0);
        lambdaQueryWrapper.orderByDesc(LitemallGiftCard::getAddTime);
        IPage<LitemallGiftCard> giftCards = litemallGiftCardService.page(new Page<>(pageReqVO.getPage(),pageReqVO.getLimit()),lambdaQueryWrapper);

        Map<Integer, LitemallAdmin> adminMap = litemallAdminService.getAdminMap(CollectionUtils.convertList(giftCards.getRecords(), LitemallGiftCard::getAddUserId));
        Map<Integer, LitemallGiftCardClassification> cardClassificationMap = litemallGiftCardClassificationService.getClassificationMap(CollectionUtils.convertList(giftCards.getRecords(), LitemallGiftCard::getClassificationId));
        Page<AdminGiftCardPageRespVO> adminGiftCardPageRespPage = BeanUtil.copyPage(giftCards, AdminGiftCardPageRespVO.class);
        adminGiftCardPageRespPage.getRecords().forEach(item->{
            MapUtils.findAndThen(adminMap,item.getAddUserId(),user -> item.setAddUserName(user.getUsername()));
            MapUtils.findAndThen(cardClassificationMap,item.getClassificationId(),cardClassification -> item.setClassificationName(cardClassification.getClassificationName()));
        });
        return ResponseUtil.okPage(adminGiftCardPageRespPage);
    }

    @ApiOperation("详情")
    @GetMapping("/detail")
    @LogAnno
    public Object detail(@NotNull Integer id) {
        return ResponseUtil.ok(litemallGiftCardService.findById(id));
    }


    @ApiOperation("创建")
    @PostMapping("/create")
    @LogAnno
    public Object create(@RequestBody @Valid LitemallGiftCard card, @LoginAdminId Integer userId) throws UnknownHostException {
        //生成礼物卡编号

        String cardNo = generatorNo();
        cardNo = cardNo.substring(0, cardNo.length() > 20 ? 20 : cardNo.length());
        card.setCardNo(IdUtil.simpleUUID());
        card.setStatus(0);
        card.setAddUserId(userId);
        litemallGiftCardService.add(card);
        return ResponseUtil.ok("礼物卡添加成功");
    }

    @ApiOperation("更新")
    @PutMapping("/update")
    @LogAnno
    public Object update(@RequestBody LitemallGiftCard card) {
        litemallGiftCardService.update(card);
        return ResponseUtil.ok("礼物卡更新成功");
    }

    @ApiOperation("删除")
    @DeleteMapping("/delete")
    @LogAnno
    public Object delete(@NotNull Integer id) {
        litemallGiftCardService.deleteById(id);
        return ResponseUtil.ok("礼物卡删除成功");
    }


    @ApiOperation("修改礼物卡状态")
    @PutMapping("/updateStatus")
    @LogAnno
    public Object updateStatus(@RequestParam("id") Integer id) {
        String msg = "";
        LitemallGiftCard litemallGiftCard = litemallGiftCardService.findById(id);
        if (litemallGiftCard.getStatus() == Constants.GIFT_CARD_STATUS_NEW) {
            litemallGiftCard.setStatus(Constants.GIFT_CARD_STATUS_PUSHED);
            msg = "礼物卡上架成功";
        } else if (litemallGiftCard.getStatus() == Constants.GIFT_CARD_STATUS_PUSHED) {
            litemallGiftCard.setStatus(Constants.GIFT_CARD_STATUS_PULLED);
            msg = "礼物卡下架成功";
        } else if (litemallGiftCard.getStatus() == Constants.GIFT_CARD_STATUS_PULLED) {
            litemallGiftCard.setStatus(Constants.GIFT_CARD_STATUS_PUSHED);
            msg = "礼物卡上架成功";
        }

        litemallGiftCardService.update(litemallGiftCard);

        return ResponseUtil.ok(msg);
    }


    @ApiOperation("虚拟卡总统计数据")
    @GetMapping("statisticTotal")
    @LogAnno
    public Object statisticTotal(AdminVirtualGiftCardStatisticPageReqVO reqVO) {
        LambdaQueryWrapper<LitemallGiftCard> queryWrapper = Wrappers.lambdaQuery(LitemallGiftCard.class);
        queryWrapper.eq(LitemallGiftCard::getType, 1);
        Optional.ofNullable(reqVO.getClassificationId()).ifPresent(id -> queryWrapper.eq(LitemallGiftCard::getClassificationId, id));
        Optional.ofNullable(reqVO.getGiftCardName()).filter(StrUtil::isNotEmpty).ifPresent(name -> queryWrapper.like(LitemallGiftCard::getName, name));
        Optional.ofNullable(reqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> queryWrapper.between(LitemallGiftCard::getAddTime, range[0], range[1]));
        List<LitemallGiftCard> litemallGiftCards = litemallGiftCardService.list(queryWrapper);
        List<Integer> GiftCardsIds = CollStreamUtil.toList(litemallGiftCards, LitemallGiftCard::getId);
        if(CollUtil.isEmpty(GiftCardsIds)){
            return  ResponseUtil.ok(new GiftCardStatisticVo());
        }
        List<LitemallGiftCardUser> litemallGiftCardUsers = litemallGiftCardUserService.list(Wrappers.lambdaQuery(LitemallGiftCardUser.class)
                .in(LitemallGiftCardUser::getGiftCardId, GiftCardsIds));
        List<LitemallGiftCardUserLog> litemallGiftCardUserLogs = new ArrayList<>();
        if(litemallGiftCardUsers.size() >0 ){
            LambdaQueryWrapper<LitemallGiftCardUserLog> giftCardUserLogLambdaQueryWrapper = new LambdaQueryWrapper<>();
            giftCardUserLogLambdaQueryWrapper.eq(reqVO.getShopId()!=null,LitemallGiftCardUserLog::getShopId, reqVO.getShopId());
            giftCardUserLogLambdaQueryWrapper.in(LitemallGiftCardUserLog::getCardUserId, CollectionUtils.convertList(litemallGiftCardUsers,LitemallGiftCardUser::getId));

            litemallGiftCardUserLogs = litemallGiftCardUserLogService.list(giftCardUserLogLambdaQueryWrapper);
        }

        GiftCardStatisticVo giftCardStatisticVo = getVo(litemallGiftCards,litemallGiftCardUsers,litemallGiftCardUserLogs,(byte)1,null);
        return ResponseUtil.ok(giftCardStatisticVo);
    }

    @ApiOperation("查询虚拟卡每个礼物卡的统计数据集合")
    @GetMapping("queryVirtualGiftCardStatistics")
    @LogAnno
    public Object getVirtualGiftCardStatistics(AdminVirtualGiftCardStatisticPageReqVO reqVO) {
        LambdaQueryWrapper<LitemallGiftCard> queryWrapper = Wrappers.lambdaQuery(LitemallGiftCard.class);
        queryWrapper.eq(LitemallGiftCard::getType, 1);
        Optional.ofNullable(reqVO.getClassificationId()).ifPresent(id -> queryWrapper.eq(LitemallGiftCard::getClassificationId, id));
        Optional.ofNullable(reqVO.getGiftCardName()).filter(StrUtil::isNotEmpty).ifPresent(name -> queryWrapper.like(LitemallGiftCard::getName, name));
        Optional.ofNullable(reqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> queryWrapper.between(LitemallGiftCard::getUpdateTime, range[0], range[1]));
        IPage<LitemallGiftCard> litemallGiftCards = litemallGiftCardService.page(new Page<>(reqVO.getPage(), reqVO.getLimit()), queryWrapper);

        List<GiftCardStatisticVo> vos = litemallGiftCards.getRecords().stream().map(card ->{
            List<LitemallGiftCardUser> litemallGiftCardUsers = litemallGiftCardUserService.list(Wrappers.lambdaQuery(LitemallGiftCardUser.class)
                    .eq(LitemallGiftCardUser::getGiftCardId, card.getId()));
            List<LitemallGiftCardUserLog> litemallGiftCardUserLogs = new ArrayList<>();
            if(litemallGiftCardUsers.size()>0){
                LambdaQueryWrapper<LitemallGiftCardUserLog> giftCardUserLogLambdaQueryWrapper = new LambdaQueryWrapper<>();
                giftCardUserLogLambdaQueryWrapper.eq(reqVO.getShopId()!=null,LitemallGiftCardUserLog::getShopId, reqVO.getShopId());
                giftCardUserLogLambdaQueryWrapper.in(LitemallGiftCardUserLog::getCardUserId, CollectionUtils.convertList(litemallGiftCardUsers,LitemallGiftCardUser::getId));

               litemallGiftCardUserLogs = litemallGiftCardUserLogService.list(giftCardUserLogLambdaQueryWrapper);
            }

            GiftCardStatisticVo giftCardStatisticVo = getVo(Arrays.asList(card),litemallGiftCardUsers,litemallGiftCardUserLogs,(byte)1,card.getId());
            return giftCardStatisticVo;
        }).collect(Collectors.toList());

        return ResponseUtil.okPage(litemallGiftCards,vos);
    }

    @ApiOperation("实体礼物卡-「删除｜物理删除」")
    @ApiImplicitParam(name = "id",value = "礼物卡用户ID")
    @GetMapping("/entityRemove")
    @LogAnno
    public Object entityRemove(@RequestParam("id") Integer id){
        return litemallGiftCardUserService.removeById(id)?ResponseUtil.ok():ResponseUtil.fail();
    }


    @ApiOperation("虚拟卡每个礼物卡的统计数据集合")
    @GetMapping("singleStatisticTotal")
    @LogAnno
    public Object singleStatisticTotal(AdminGiftCardEntityTypeStatisticDetailsPageReqVO pageReqVO){
        // 通过 pageReqVO 获取查询条件
        List<LitemallGiftCard> giftCardList = litemallGiftCardService.list(Wrappers.lambdaQuery(LitemallGiftCard.class)
                .eq(LitemallGiftCard::getId,pageReqVO.getGiftCardId())
        );

        LambdaQueryWrapper<LitemallGiftCardUser> wrapper = new LambdaQueryWrapper<>();
        Optional.ofNullable(pageReqVO.getCardNo())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(cardNo -> wrapper.like(LitemallGiftCardUser::getCardNumber, cardNo));
        Optional.ofNullable(pageReqVO.getUserName())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(userName -> wrapper.like(LitemallGiftCardUser::getUserName, userName));
        Optional.ofNullable(pageReqVO.getStatus())
                .ifPresent(status -> wrapper.eq(LitemallGiftCardUser::getStatus, status));
        Optional.ofNullable(pageReqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> wrapper.between(LitemallGiftCardUser::getUpdateTime, range[0], range[1]));
        wrapper.in(LitemallGiftCardUser::getGiftCardId, CollStreamUtil.toList(giftCardList, LitemallGiftCard::getId));
        wrapper.orderByDesc(LitemallGiftCardUser::getBindTime);
        List<LitemallGiftCardUser> litemallGiftCardUsers = litemallGiftCardUserService.list(wrapper);
        List<LitemallGiftCardUserLog> litemallGiftCardUserLogs =new ArrayList<>();
        if(litemallGiftCardUsers.size() > 0){
            LambdaQueryWrapper<LitemallGiftCardUserLog> giftCardUserLogLambdaQueryWrapper = new LambdaQueryWrapper<>();
            giftCardUserLogLambdaQueryWrapper.in(LitemallGiftCardUserLog::getCardUserId, CollectionUtils.convertList(litemallGiftCardUsers,LitemallGiftCardUser::getId));
            litemallGiftCardUserLogs = litemallGiftCardUserLogService.list(giftCardUserLogLambdaQueryWrapper);
        }

        GiftCardStatisticVo giftCardStatisticVo = getVo(giftCardList,litemallGiftCardUsers,litemallGiftCardUserLogs,(byte)1,pageReqVO.getGiftCardId());
        return ResponseUtil.ok(giftCardStatisticVo);
    }


    /**
     * 实体数据总
     * 实体卡总统计数据
     *
     * @return {@link Object}
     */
    @GetMapping("entityStatisticTotal")
    @LogAnno
    public Object entityStatisticTotal(AdminGiftCardEntityTypeStatisticPageReqVO pageReqVO) {
        // 1. 查询所有类型为2的礼品卡
        LambdaQueryWrapper<LitemallGiftCard> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LitemallGiftCard::getType, 2);
        Optional.ofNullable(pageReqVO.getClassificationId())
                .ifPresent(classificationId -> queryWrapper.eq(LitemallGiftCard::getClassificationId, classificationId));
        Optional.ofNullable(pageReqVO.getDateRange())
                .filter(r -> r.length == 2)
                .ifPresent(r -> queryWrapper.between(LitemallGiftCard::getAddTime, r[0], r[1]));
        Optional.ofNullable(pageReqVO.getGiftCardName())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(name -> queryWrapper.like(LitemallGiftCard::getName, name));

        List<LitemallGiftCard> litemallGiftCards = litemallGiftCardService.list(queryWrapper);
        if (CollUtil.isEmpty(litemallGiftCards)) {
            return ResponseUtil.ok(new GiftCardStatisticVo());
        }

        // 2. 提取所有卡片ID
        List<Integer> cardIds = CollStreamUtil.toList(litemallGiftCards,LitemallGiftCard::getId);

        // 3. 查询所有礼品卡用户 发行数量
        List<LitemallGiftCardUser> litemallGiftCardUsers = litemallGiftCardUserService.list(
                Wrappers.lambdaQuery(LitemallGiftCardUser.class)
                        .in(LitemallGiftCardUser::getGiftCardId, cardIds)
        );

        if (CollUtil.isEmpty(litemallGiftCardUsers)) {
            return ResponseUtil.ok(new GiftCardStatisticVo());
        }
        // 未使用数量
        Long noUseNum = litemallGiftCardUsers.stream().filter(giftCardUser -> giftCardUser.getStatus() == 0).count();
        Integer bindNum = (int) litemallGiftCardUsers.stream().filter(user -> user.getEntityCardCode() != null).count();
        Long stopNum = litemallGiftCardUsers.stream().filter(giftCardUser -> giftCardUser.getStatus() == 2).count();

        // 总余额
        BigDecimal totalAmount = BigDecimalUtil.sum(litemallGiftCardUsers,LitemallGiftCardUser::getAmount);

        // 总消费
        List<LitemallGiftCardUserLog> litemallGiftCardUserLogs = litemallGiftCardUserLogService.list(Wrappers.lambdaQuery(LitemallGiftCardUserLog.class)
                .eq(pageReqVO.getShopId() != null,LitemallGiftCardUserLog::getShopId, pageReqVO.getShopId())
                .in(LitemallGiftCardUserLog::getCardNumber,CollStreamUtil.toSet(litemallGiftCardUsers,LitemallGiftCardUser::getCardNumber))
        );

        //总充值金额
        BigDecimal totalRechargeAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs, LitemallGiftCardUserLog::getAmount, logs -> logs.getType() == Constants.LOG_GIFTCARD_RECHARGE || logs.getType() == Constants.LOG_GIFTCARD_SHARE);

        BigDecimal useAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs,LitemallGiftCardUserLog::getAmount,logs -> logs.getType() == Constants.LOG_GIFTCARD_CONSUME);

        //使用数量
        Integer inUseNum = (int) litemallGiftCardUsers.stream().filter(user -> user.getStatus() == 1).count();
        GiftCardStatisticVo giftCardStatisticVo = new GiftCardStatisticVo();
        giftCardStatisticVo.setNumbers(litemallGiftCardUsers.size());
        giftCardStatisticVo.setUseAmount(useAmount);
        giftCardStatisticVo.setInUseNum(inUseNum);
        giftCardStatisticVo.setTotalAmount(totalAmount);
        giftCardStatisticVo.setNoUseNum(noUseNum.intValue());
        giftCardStatisticVo.setStopNum(stopNum.intValue());
        giftCardStatisticVo.setBindNum(bindNum);
        giftCardStatisticVo.setTotalRechargeAmount(totalRechargeAmount);
        return ResponseUtil.ok(giftCardStatisticVo);
    }

    @ApiOperation("实体卡统计")
    @GetMapping("entityTypeStatisticTotal")
    @LogAnno
    public Object entityTypeStatisticTotal(AdminGiftCardEntityTypeStatisticPageReqVO pageReqVO) {
        // 构建查询条件
        LambdaQueryWrapper<LitemallGiftCard> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LitemallGiftCard::getType, 2);
        Optional.ofNullable(pageReqVO.getClassificationId())
                .ifPresent(classificationId -> queryWrapper.eq(LitemallGiftCard::getClassificationId, classificationId));
        Optional.ofNullable(pageReqVO.getDateRange())
                .filter(r -> r.length == 2)
                .ifPresent(r -> queryWrapper.between(LitemallGiftCard::getAddTime, r[0], r[1]));
        Optional.ofNullable(pageReqVO.getGiftCardName())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(name -> queryWrapper.like(LitemallGiftCard::getName, name));

        // 分页查询
        IPage<LitemallGiftCard> litemallGiftCards = litemallGiftCardService.page(
                new Page<>(pageReqVO.getPage(), pageReqVO.getLimit()),
                queryWrapper
        );
        if (litemallGiftCards.getTotal() == 0) {
            return ResponseUtil.okPage(new Page<>());
        }

        List<Integer> cardIds = CollectionUtils.convertList(litemallGiftCards.getRecords(),LitemallGiftCard::getId);

        // 批量查询所有用户
        List<LitemallGiftCardUser> allUsers = litemallGiftCardUserService.queryAllByGiftCardIds(cardIds, null);
        Map<Integer, List<LitemallGiftCardUser>> userMap = allUsers.stream()
                .collect(Collectors.groupingBy(LitemallGiftCardUser::getGiftCardId));

        // 生成 userId -> user 映射（供日志关联卡用）
        Map<Integer, LitemallGiftCardUser> userIdMap = allUsers.stream()
                .collect(Collectors.toMap(LitemallGiftCardUser::getId, Function.identity()));

        // 批量查询所有日志
        LambdaQueryWrapper<LitemallGiftCardUserLog> logQueryWrapper = new LambdaQueryWrapper<>();
        logQueryWrapper.in(LitemallGiftCardUserLog::getCardNumber, allUsers.size()==0?Arrays.asList(0):CollStreamUtil.toSet(allUsers, LitemallGiftCardUser::getCardNumber));
        if (pageReqVO.getShopId() != null) {
            logQueryWrapper.eq(LitemallGiftCardUserLog::getShopId, pageReqVO.getShopId());
        }
        List<LitemallGiftCardUserLog> allLogs = litemallGiftCardUserLogService.list(logQueryWrapper);

        // 日志归类到 GiftCardId（通过 user 映射）
        Map<Integer, List<LitemallGiftCardUserLog>> logMap = allLogs.stream()
                .filter(log -> userIdMap.containsKey(log.getCardUserId()))
                .collect(Collectors.groupingBy(log -> userIdMap.get(log.getCardUserId()).getGiftCardId()));

        List<GiftCardStatisticVo> vos = litemallGiftCards.getRecords().parallelStream().map(card -> {
            List<LitemallGiftCardUser> users = userMap.getOrDefault(card.getId(), Collections.emptyList());
            List<LitemallGiftCardUserLog> logs = logMap.getOrDefault(card.getId(), Collections.emptyList());

            List<LitemallGiftCard> singleCardList = Collections.singletonList(card);

            GiftCardStatisticVo vo = getEntityVo(singleCardList, users, logs, (byte) 2, card.getId());
            vo.setAddTime(card.getAddTime());

            // 分类名
            LitemallGiftCardClassification classification = litemallGiftCardClassificationService.findById(card.getClassificationId());
            vo.setClassificationName(classification == null ? null : classification.getClassificationName());
            return vo;
        }).collect(Collectors.toList());

        return ResponseUtil.okPage(litemallGiftCards, vos);
    }


    @ApiOperation("实体卡每个礼物卡的统计数据集合")
    @GetMapping("entitySingleTypeStatisticTotal")
    @LogAnno
    public Object entitySingleTypeStatisticTotal(Integer giftCardId){
        LitemallGiftCard card = litemallGiftCardService.findById(giftCardId);
            List<LitemallGiftCardUser> litemallGiftCardUsers = litemallGiftCardUserService.queryAllByGiftCardId(card.getId(),null);
            List<LitemallGiftCardUserLog> litemallGiftCardUserLogs = litemallGiftCardUserLogService.queryAllByShopId(null);
            List<LitemallGiftCard> singleCard = new ArrayList<>();
            singleCard.add(card);
            GiftCardStatisticVo giftCardStatisticVo = getEntityVo(singleCard,litemallGiftCardUsers,litemallGiftCardUserLogs,(byte)2,card.getId());

        return ResponseUtil.ok(giftCardStatisticVo);
    }



    @ApiOperation("批量启用/停用礼品卡用户")
    @PutMapping("/toggleUserStatus")
    @LogAnno
    public Object toggleUserStatus(@RequestBody AdminGiftToggleUserStatusReqVO reqVO) {
        List<Integer> ids = reqVO.getIds();
        int status = reqVO.getStatus();

        if (CollUtil.isEmpty(ids) || (status != 1 && status != 2)) {
            return ResponseUtil.fail(400, "参数不合法");
        }

        List<LitemallGiftCardUser> users = litemallGiftCardUserService.listByIds(ids);
        for (LitemallGiftCardUser user : users) {
            user.setStatus(status);
        }
        boolean updated = litemallGiftCardUserService.updateBatchById(users);
        return updated ? ResponseUtil.ok("批量状态更新成功") : ResponseUtil.fail("更新失败");
    }

    @ApiOperation("实体类型统计概览")
    @GetMapping("singleEntityTypeStatisticTotal")
    @LogAnno
    public Object singleEntityTypeStatisticTotal(AdminGiftCardEntityTypeStatisticDetailsPageReqVO pageReqVO){
        LitemallGiftCard giftCard = litemallGiftCardService.findById(pageReqVO.getGiftCardId());
        LambdaQueryWrapper<LitemallGiftCardUser> wrapper = new LambdaQueryWrapper<>();
        Optional.ofNullable(pageReqVO.getCardNo())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(cardNo -> wrapper.like(LitemallGiftCardUser::getCardNumber, cardNo));
        Optional.ofNullable(pageReqVO.getUserName())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(userName -> wrapper.like(LitemallGiftCardUser::getUserName, userName));
        Optional.ofNullable(pageReqVO.getStatus())
                .ifPresent(status -> wrapper.eq(LitemallGiftCardUser::getStatus, status));
        wrapper.eq(LitemallGiftCardUser::getGiftCardId, giftCard.getId());
        Optional.ofNullable(pageReqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> wrapper.between(LitemallGiftCardUser::getAddTime, range[0], range[1]));
        Optional.ofNullable(pageReqVO.getBindStatus()).ifPresent(status -> {
            if (status == 0) {
                wrapper.isNull(LitemallGiftCardUser::getEntityCardCode);
            } else if (status == 1) {
                wrapper.isNotNull(LitemallGiftCardUser::getEntityCardCode);
            }
        });
        wrapper.orderByDesc(LitemallGiftCardUser::getBindTime);

        List<LitemallGiftCardUser> litemallGiftCardUsers = litemallGiftCardUserService.list(wrapper);
        LambdaQueryWrapper<LitemallGiftCardUserLog> giftCardUserLogLambdaQueryWrapper = new LambdaQueryWrapper<>();
        giftCardUserLogLambdaQueryWrapper.in(LitemallGiftCardUserLog::getCardUserId, litemallGiftCardUsers.size()==0?Arrays.asList(0):
                CollectionUtils.convertSet(litemallGiftCardUsers,LitemallGiftCardUser::getId));
        List<LitemallGiftCardUserLog> currentGiftCardLogs = litemallGiftCardUserLogService.list(giftCardUserLogLambdaQueryWrapper);
        GiftCardStatisticVo giftCardStatisticVo = getEntityVo(Arrays.asList(giftCard),litemallGiftCardUsers,currentGiftCardLogs,(byte)2,pageReqVO.getGiftCardId());
        return ResponseUtil.ok(giftCardStatisticVo);
    }

    @ApiOperation("用户类型统计")
    @GetMapping("typeUserStatistic")
    @LogAnno
    public Object typeUserStatistic(AdminGiftCardEntityTypeStatisticDetailsPageReqVO pageReqVO){
        // 通过 pageReqVO 获取查询条件
        LitemallGiftCard giftCard = litemallGiftCardService.getById(pageReqVO.getGiftCardId());

        LambdaQueryWrapper<LitemallGiftCardUser> wrapper = new LambdaQueryWrapper<>();
        Optional.ofNullable(pageReqVO.getCardNo())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(cardNo -> wrapper.like(LitemallGiftCardUser::getCardNumber, cardNo));
        Optional.ofNullable(pageReqVO.getUserName())
                .filter(StrUtil::isNotEmpty)
                .ifPresent(userName -> wrapper.like(LitemallGiftCardUser::getUserName, userName));
        Optional.ofNullable(pageReqVO.getStatus())
                .ifPresent(status -> wrapper.eq(LitemallGiftCardUser::getStatus, status));
        wrapper.eq(LitemallGiftCardUser::getGiftCardId, giftCard.getId());
        Optional.ofNullable(pageReqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> wrapper.between(LitemallGiftCardUser::getAddTime, range[0], range[1]));
        Optional.ofNullable(pageReqVO.getBindStatus()).ifPresent(status -> {
            if (status == 0) {
                wrapper.isNull(LitemallGiftCardUser::getEntityCardCode);
            } else if (status == 1) {
                wrapper.isNotNull(LitemallGiftCardUser::getEntityCardCode);
            }
        });
        wrapper.orderByDesc(LitemallGiftCardUser::getBindTime);

        IPage<LitemallGiftCardUser> giftCardUsers = litemallGiftCardUserService.page(
                new Page<>(pageReqVO.getPage(), pageReqVO.getLimit()),
                wrapper
        );

        List giftCardUserVos = new ArrayList<>();
        for (LitemallGiftCardUser giftCardUser : giftCardUsers.getRecords()) {
            LitemallGiftCardUserVo cardUserVo = new LitemallGiftCardUserVo();
            BeanUtils.copyProperties(giftCardUser, cardUserVo);
            List<LitemallGiftCardUserLog> litemallGiftCardUserLogs = new ArrayList<>();
            if( giftCardUser.getUserId() != null){
                LambdaQueryWrapper<LitemallGiftCardUserLog> giftCardUserLogLambdaQueryWrapper = new LambdaQueryWrapper<>();
                giftCardUserLogLambdaQueryWrapper.eq(LitemallGiftCardUserLog::getCardUserId, giftCardUser.getId());
                litemallGiftCardUserLogs = litemallGiftCardUserLogService.list(giftCardUserLogLambdaQueryWrapper);
            }

            BigDecimal useAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs, LitemallGiftCardUserLog::getAmount, logs -> logs.getType() == Constants.LOG_GIFTCARD_CONSUME);

            cardUserVo.setUseAmount(useAmount);

            BigDecimal totalRechargeAmount = litemallGiftCardUserLogs.stream()
                    .filter(log -> log.getType() == Constants.LOG_GIFTCARD_RECHARGE || log.getType() == Constants.LOG_GIFTCARD_SHARE )
                    .map(LitemallGiftCardUserLog::getAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            cardUserVo.setTotalRechargeAmount(totalRechargeAmount);

            LitemallUser user = litemallUserService.findById(giftCardUser.getUserId());
            if(user != null){
                cardUserVo.setNikeName(user.getNickname());
                cardUserVo.setUserName(user.getUsername());
                cardUserVo.setMobile(user.getMobile());
            }

            giftCardUserVos.add(cardUserVo);
        }
        giftCardUsers.setRecords(giftCardUserVos);
        return ResponseUtil.okPage(giftCardUsers);
    }


    @ApiOperation(value = "用户礼物卡明细")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId",value = "用户ID"),
            @ApiImplicitParam(name = "cardNumber",value = "卡号"),
            @ApiImplicitParam(name = "page",value = "页"),
            @ApiImplicitParam(name = "limit",value = "数")
    })
    @GetMapping(value = "giftCardUserDetail")
    public ResponseUtil.Response giftCardUserDetail(@RequestParam("userId") Integer userId,@RequestParam(defaultValue = "1") Integer page,
                                                    @RequestParam(value = "cardNumber",defaultValue = "")String cardNumber,
                                                    @RequestParam(defaultValue = "10") Integer limit){
        List<GiftCardUserDetailVo> giftCardUserDetailVos = CollUtil.newArrayList();
        for(LitemallGiftCardUserLog litemallGiftCardUserLogs : litemallGiftCardUserLogService.list(Wrappers.lambdaQuery(LitemallGiftCardUserLog.class)
                .eq(LitemallGiftCardUserLog::getAddUserId, userId)
                .like(StrUtil.isNotEmpty(cardNumber),LitemallGiftCardUserLog::getCardNumber,cardNumber.trim())
                .orderByDesc(LitemallGiftCardUserLog::getAddTime))){
            LitemallGiftCardOrder litemallGiftCardOrder = litemallGiftCardOrderService.findById(litemallGiftCardUserLogs.getOrderId());
            GiftCardUserDetailVo giftCardUserDetailVo = GiftCardUserDetailVo.builder().build();
            BeanUtils.copyProperties(litemallGiftCardUserLogs,giftCardUserDetailVo);
            if(ObjectUtil.isNotEmpty(litemallGiftCardOrder)){BeanUtils.copyProperties(litemallGiftCardOrder,giftCardUserDetailVo);}
            giftCardUserDetailVos.add(giftCardUserDetailVo);
        }
        Pageable pageable = PageRequest.of(page -1 ,limit);
        return ResponseUtil.ok(PageUtil.getPageLumierePayMemberUserLogVo(pageable,giftCardUserDetailVos));
    }


    @ApiOperation("用户礼物卡订单详情")
    @GetMapping(value = "giftCardUserOrderDetail")
    public ResponseUtil.Response giftCardUserOrderDetail(@RequestParam("giftCardOrderId") Integer id){
        LitemallGiftCardOrder giftCardOrder = litemallGiftCardOrderService.getOne(Wrappers.lambdaQuery(LitemallGiftCardOrder.class)
                .eq(LitemallGiftCardOrder::getId, id));
        if(ObjectUtil.isNull(giftCardOrder)){
            return  ResponseUtil.success(LitemallGiftCardOrderVO.builder().cardNumber("------").build());
        }
        //返回实体
        LitemallGiftCardOrderVO giftCardOrderVO = LitemallGiftCardOrderVO.builder().build();
        if(StrUtil.isBlank(giftCardOrder.getAddUserName())){
            String username = litemallUserService.findById(giftCardOrder.getUserId()).getUsername();
            giftCardOrderVO.setAddUserName(username);
        }
        String username = litemallUserService.findById(giftCardOrder.getUserId()).getUsername();
        giftCardOrderVO.setUsername(username);
        String shopname = litemallShopService.findById(giftCardOrder.getShopId()).getName();
        giftCardOrderVO.setShopname(shopname);
        BeanUtils.copyProperties(giftCardOrder,giftCardOrderVO);
        return ResponseUtil.success(giftCardOrderVO);
    }

    @ApiOperation("礼物卡用户消费记录")
    @GetMapping("comsuptionDetails")
    @LogAnno
    public Object comsuptionDetails(@RequestParam("giftCardUserId") Integer giftCardUserId,
                                   Integer type,
            @RequestParam("page")Integer page,
            @RequestParam("limit")Integer limit){
        LitemallGiftCardUser litemallGiftCardUser = litemallGiftCardUserService.findById(giftCardUserId);
        if(litemallGiftCardUser == null){return ResponseUtil.fail(444,"礼物卡不存在");}

        IPage<LitemallGiftCardUserLog> giftCardUserLogs = litemallGiftCardUserLogService.page(new Page<>(page,limit),Wrappers.lambdaQuery(LitemallGiftCardUserLog.class)
                .eq(type!=null,LitemallGiftCardUserLog::getType,type)
                .eq(LitemallGiftCardUserLog::getCardNumber, litemallGiftCardUser.getCardNumber()).orderByDesc(LitemallGiftCardUserLog::getAddTime));

        List vos = giftCardUserLogs.getRecords().stream().map(giftLog -> {
            LitemallGiftCardUser u = litemallGiftCardUserService.findById(giftLog.getCardUserId());
            LitemallUser user = litemallUserService.findById(u.getUserId());
            LitemallShop shop = litemallShopService.findById(giftLog.getShopId());
            LitemallGiftCard card = litemallGiftCardService.findById(u != null ? u.getGiftCardId() : null);
            GiftCardUserLogVo vo = new GiftCardUserLogVo();
            vo.setAddUserName(user != null ? user.getUsername() : u.getUserName());
            vo.setCardNo(card.getCardNo());
            vo.setCardName(card.getName());
            vo.setType(giftLog.getType());
            vo.setAmount(giftLog.getAmount());
            vo.setConsumeTime(giftLog.getAddTime());
            vo.setContent(giftLog.getContent());
            vo.setShopName(shop != null ? shop.getName() : null);
            vo.setOrderSource(giftLog.getOrderSource());
            return vo;
        }).collect(Collectors.toList());
        giftCardUserLogs.setRecords(vos);
        return ResponseUtil.okPage(giftCardUserLogs);
    }



    public String generatorNo() throws UnknownHostException {
        //获取本机Ip
        String ip = InetAddress.getLocalHost().getHostAddress();

        //获取时间
        String now = LocalDateTime.now().toString();

        return ip + "-" + now;
    }

    public GiftCardStatisticVo getVo(List<LitemallGiftCard> litemallGiftCards,List<LitemallGiftCardUser> litemallGiftCardUsers,List<LitemallGiftCardUserLog> litemallGiftCardUserLogs,
                                     Byte type,Integer giftCardId){
        GiftCardStatisticVo giftCardStatisticVo = new GiftCardStatisticVo();
        if(litemallGiftCards == null || litemallGiftCards.size() == 0){
            return giftCardStatisticVo;
        }

        //总的礼物卡数量
        Integer numbers = litemallGiftCards.stream().mapToInt(card -> card.getNumbers()).reduce(Integer::sum).getAsInt();
        giftCardStatisticVo.setNumbers(numbers);
        giftCardStatisticVo.setGiftCardId(litemallGiftCards.get(0).getId());
        giftCardStatisticVo.setName( litemallGiftCards.get(0).getName());

        //礼物卡分类
        LitemallGiftCardClassification cardClassification = litemallGiftCardClassificationService.findById(litemallGiftCards.get(0).getClassificationId());
        giftCardStatisticVo.setClassificationName(cardClassification != null ? cardClassification.getClassificationName() : null);

        //更新时间
        giftCardStatisticVo.setUpdateTime(litemallGiftCards.get(0).getUpdateTime());

        //销售数量
        giftCardStatisticVo.setSaledNum(litemallGiftCardUsers.size());


        //使用数量
        Integer inUseNum = (int) litemallGiftCardUsers.stream().filter(user -> user.getStatus() == 1).count();
        giftCardStatisticVo.setInUseNum(inUseNum);

        giftCardStatisticVo.setStopNum((int) litemallGiftCardUsers.stream().filter(user -> user.getStatus() == 2).count());

        //未使用数量=未领取数量+未激活数量
        Integer noUseNum = (int) litemallGiftCardUsers.stream().filter(user -> user.getStatus() == 0).count();
        giftCardStatisticVo.setNoUseNum(noUseNum);

        BigDecimal totalAmount = BigDecimalUtil.sum(litemallGiftCardUsers,LitemallGiftCardUser::getAmount);

        //订单完成的金额
        //BigDecimal orderAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs,LitemallGiftCardUserLog::getAmount,logs -> logs.getType() == Constants.GIFT_CARD_PAY_STATUS_COMSUMPTION;

        //总退款
        //BigDecimal orderReturnAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs,LitemallGiftCardUserLog::getAmount,logs -> logs.getType() == Constants.LOG_GIFTCARD_REFUND);

        BigDecimal useAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs,LitemallGiftCardUserLog::getAmount,logs -> logs.getType() == Constants.LOG_GIFTCARD_CONSUME);

        giftCardStatisticVo.setUseAmount(useAmount);

        //总充值金额
        BigDecimal totalRechargeAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs,LitemallGiftCardUserLog::getAmount,logs -> logs.getType() == Constants.LOG_GIFTCARD_RECHARGE || logs.getType() == Constants.LOG_GIFTCARD_SHARE);

        giftCardStatisticVo.setTotalRechargeAmount(totalRechargeAmount);

        giftCardStatisticVo.setTotalAmount(totalAmount);

        return giftCardStatisticVo;
    }


    public GiftCardStatisticVo getEntityVo(List<LitemallGiftCard> litemallGiftCards,List<LitemallGiftCardUser> litemallGiftCardUsers,List<LitemallGiftCardUserLog> litemallGiftCardUserLogs,
                                     Byte type,Integer giftCardId){
        GiftCardStatisticVo giftCardStatisticVo = new GiftCardStatisticVo();
        if(litemallGiftCards == null || litemallGiftCards.size() == 0){
            return giftCardStatisticVo;
        }

        //总的礼物卡数量
        Integer numbers = litemallGiftCards.stream().mapToInt(card -> card.getNumbers()).reduce(Integer::sum).getAsInt();
        giftCardStatisticVo.setNumbers(numbers);

        Integer bindNum = (int) litemallGiftCardUsers.stream().filter(user -> user.getEntityCardCode() != null).count();
        giftCardStatisticVo.setBindNum(bindNum);

        giftCardStatisticVo.setGiftCardId(litemallGiftCards.get(0).getId());
        giftCardStatisticVo.setName( litemallGiftCards.get(0).getName());

        //销售数量
        giftCardStatisticVo.setSaledNum(litemallGiftCardUsers.size());


        //使用数量
        Integer inUseNum = (int) litemallGiftCardUsers.stream().filter(user -> user.getStatus() == 1).count();
        giftCardStatisticVo.setInUseNum(inUseNum);

        //未使用数量=未领取数量+未激活数量
        Integer noUseNum = (int) litemallGiftCardUsers.stream().filter(user -> user.getStatus() == 0).count();
        giftCardStatisticVo.setNoUseNum(noUseNum);

        //已停用数量
        Long stopNum = litemallGiftCardUsers.stream().filter(user -> user.getStatus() == 2).count();

        giftCardStatisticVo.setStopNum(stopNum.intValue());

        BigDecimal totalAmount = BigDecimalUtil.sum(litemallGiftCardUsers, LitemallGiftCardUser::getAmount);

        //订单完成的金额
        BigDecimal orderAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs, LitemallGiftCardUserLog::getAmount, logs -> logs.getType() == type);
        //总退款
        BigDecimal orderReturnAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs, LitemallGiftCardUserLog::getAmount, logs -> logs.getType() == Constants.LOG_GIFTCARD_REFUND);

        //总充值金额
        BigDecimal totalRechargeAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs, LitemallGiftCardUserLog::getAmount, logs -> logs.getType() == Constants.LOG_GIFTCARD_RECHARGE || logs.getType() == Constants.LOG_GIFTCARD_SHARE);

        giftCardStatisticVo.setTotalRechargeAmount(totalRechargeAmount);
        BigDecimal useAmount = BigDecimalUtil.sum(litemallGiftCardUserLogs,LitemallGiftCardUserLog::getAmount,logs -> logs.getType() == Constants.LOG_GIFTCARD_CONSUME);

        giftCardStatisticVo.setUseAmount(useAmount);

        giftCardStatisticVo.setTotalAmount(totalAmount);
        return giftCardStatisticVo;
    }


    @ApiOperation("查询所有已启用的订阅")
    @GetMapping("queryAllPushed")
    @LogAnno
    public Object queryAllPushed(){
        return ResponseUtil.okList(litemallGiftCardService.selectEnabledList(Constants.GIFT_CARD_STATUS_PUSHED));
    }

}
